`timescale 1ns / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:
//
// Create Date:   16:07:19 07/09/2012
// Design Name:   I2CTransceiver
// Module Name:   /home/azonenberg/native/programming/achd-soc/trunk/hdl/achd-soc/testI2CTransceiver.v
// Project Name:  achd-soc
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: I2CTransceiver
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////

module testI2CTransceiver;

	// Inputs
	reg clk = 0;
	reg [15:0] clkdiv = 260;
	reg tx_en = 0;
	reg [7:0] tx_data = 0;
	reg rx_en = 0;
	reg rx_ack = 0;
	reg start_en = 0;
	reg restart_en = 0;
	reg stop_en = 0;

	// Outputs
	wire i2c_scl;
	wire tx_ack;
	wire rx_rdy;
	wire [7:0] rx_out;
	wire busy;

	// Bidirs
	wire i2c_sda;

	// Instantiate the Unit Under Test (UUT)
	I2CTransceiver uut (
		.clk(clk), 
		.clkdiv(clkdiv), 
		.i2c_scl(i2c_scl), 
		.i2c_sda(i2c_sda), 
		.tx_en(tx_en), 
		.tx_ack(tx_ack), 
		.tx_data(tx_data), 
		.rx_en(rx_en), 
		.rx_rdy(rx_rdy), 
		.rx_out(rx_out), 
		.rx_ack(rx_ack), 
		.start_en(start_en), 
		.restart_en(restart_en), 
		.stop_en(stop_en), 
		.busy(busy)
	);
	
	//Something for it to talk to
	M24LC256 eeprom (
		.A0(1'b0), 
		.A1(1'b0), 
		.A2(1'b0), 
		.WP(1'b0), 
		.SDA(i2c_sda), 
		.SCL(i2c_scl), 
		.RESET(1'b0)
		);

	//Clock oscillator
	reg ready = 0;
	initial begin
		#100;
		ready = 1;
	end
	always begin
		clk = 0;
		#5;
		clk = ready;
		#5;
	end
	
	PULLUP sda_pull(.O(i2c_sda));
	PULLUP scl_pull(.O(i2c_scl));
	
	localparam I2C_WRITE = 1'b0;
	localparam I2C_READ = 1'b1;
	
	reg[18:0] count2 = 1;
	reg[7:0] count = 1;
	reg[15:0] state = 0;
	always @(posedge clk) begin
	
		start_en <= 0;
		restart_en <= 0;
		stop_en <= 0;
		
		tx_en <= 0;
		tx_data <= 0;
		rx_en <= 0;
		rx_ack <= 0;
	
		case(state)
			0: begin
				count <= count + 1;
				if(count == 0)
					state <= 1;
			end
		
			//send start bit
			1: begin
				start_en <= 1;
				state <= 2;
			end
			
			//Device address
			2: begin
				if(!busy) begin
					tx_en <= 1;
					tx_data <= {7'b1010000, I2C_WRITE};
					state <= 3;
				end
			end
			
			//2-byte address
			3: begin
				if(!busy) begin
					tx_en <= 1;
					tx_data <= 8'h00;
					state <= 4;
				end
			end
			4: begin
				if(!busy) begin
					tx_en <= 1;
					tx_data <= 8'h00;
					state <= 5;
				end
			end
			
			//Byte write
			5: begin
				if(!busy) begin
					tx_en <= 1;
					tx_data <= 8'hA3;
					state <= 6;
				end
			end
			
			//Done
			6: begin
				if(!busy) begin
					stop_en <= 1;
					state <= 7;
					$display("Waiting for EEPROM to become ready...");
				end
			end
			
			//Ack poll
			/*
			7: begin
				if(!busy) begin
					start_en <= 1;
					state <= 8;
				end
			end
			8: begin
				if(!busy) begin
					tx_en <= 1;
					tx_data <= {7'b1010000, I2C_WRITE};
					state <= 9;
				end
			end
			9: begin
				//See if the message was acknowledged
				if(!busy) begin
					stop_en <= 1;
				
					if(tx_ack) begin
						$display("ACK");
						state <= 10;
					end
					else begin
						state <= 7;
					end
				end
			end
			*/
			7: begin
				count2 <= count2 + 1;
				if(count2 == 0)
					state <= 10;
			end
			
			//Read from address 0
			10: begin
				if(!busy) begin
					start_en <= 1;
					state <= 11;
				end
			end
			11: begin
				if(!busy) begin
					tx_en <= 1;
					tx_data <= {7'b1010000, I2C_WRITE};
					state <= 12;
				end
			end
			//2-byte address
			12: begin
				if(!busy) begin
					tx_en <= 1;
					tx_data <= 8'h00;
					state <= 13;
				end
			end
			13: begin
				if(!busy) begin
					tx_en <= 1;
					tx_data <= 8'h00;
					state <= 14;
				end
			end
			
			//Restart and send control byte again
			14: begin
				if(!busy) begin
					restart_en <= 1;
					state <= 15;
				end
			end
			15: begin
				if(!busy) begin
					tx_en <= 1;
					tx_data <= {7'b1010000, I2C_READ};
					state <= 16;
				end
			end
			
			//Read a byte of data
			//NACK it so the EEPROM stops sending
			16: begin
				if(!busy) begin
					rx_en <= 1;
					rx_ack <= 0;
					state <= 17;
				end
			end
			
			//Process the data
			17: begin
				if(rx_rdy) begin
					//TODO
					state <= 18;
				end
			end
			18: begin
				if(!busy) begin
					stop_en <= 1;
					state <= 19;
				end
			end
			
			19: begin
				
			end

		endcase
	end
      
endmodule

